#include <iostream>
#include <vector>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "Task_Work.hpp"
#include "Channel.hpp"
enum
{
    OK = 0,
    PIPEERROR,
    FORKERROR
};
class ProcessPool
{
public:
    ProcessPool(int num, work_t wo) : num_processes(num), work(wo)
    {
    }
    int InitPool() // 第三函数对象实现回调
    {
        for (int i = 0; i < num_processes; i++)
        {
            int pipefd[2] = {0};
            int n = ::pipe(pipefd); // 创建管道
            if (n < 0)
            {
                std::cout << "Pipe error" << std::endl;
                return PIPEERROR;
            }
            pid_t pid = ::fork();
            if (pid < 0)
            {
                std::cout << "Fork error" << std::endl;
                return FORKERROR;
            }
            else if (pid == 0)
            {
                ::close(pipefd[1]);   // 子进程读，关闭写
                ::dup2(pipefd[0], 0); // 管道读段重定向到stdin中;默认从标准输入读取,这样执行work函数时不需要传递读取的文件描述符pipefd[0];
                work();
                ::exit(0);
            }
            else
            {
                ::close(pipefd[0]); // 父进程写，关闭读
                // Channel ch(pipefd[1],pid);
                // channels.push_back(ch);
                channels.emplace_back(pipefd[1], pid); // 保存每个管道的写端以及对应的子进程
            }
        }
        return OK;
    }
    void DispatchTasks() // 分发任务
    {
        int sum = 10;
        int who = 0;
        while (sum--)
        {
            int task_num = tsm.Select_Tasks(); // 选择任务码

            std::cout << "-------------" << std::endl;
            std::cout << "--执行任务--" << sum << std::endl;
            std::cout << "-------------" << std::endl;
            who %= channels.size();
            Channel &ch = channels[who++];
            std::cout << ch.GetName() << std::endl;
            std::cout << task_num << std::endl;
            ch.Send(task_num);
            ::sleep(1);
        }
    }
    void CleanPool()
    {
        for (auto &ch : channels) // 关闭每个管道的写端
            ch.Close();
        for (auto &ch : channels) // 回收每个管道对应的子进程
        {
            int rid = ::waitpid(ch.Getpid(), nullptr, 0); // 阻塞式等待
            if (rid > 0)
                std::cout << rid << " wait sucess..." << std::endl;
        }
    }

private:
    int num_processes;             // 管道数（进程数）
    work_t work;                   // 任务类型
    std::vector<Channel> channels; // 进程池
};
